package com.zwb.service.config;

import com.zwb.service.filter.JwtAuthenticationFilter;
import com.zwb.service.handlers.AccessDecisionManagerImpl;
import com.zwb.service.handlers.JwtAccessDeniedHandler;
import com.zwb.service.handlers.JwtAuthenticationEntryPoint;
import com.zwb.service.handlers.SecureDataSourceImpl;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import javax.servlet.Filter;

/**
 * @author 头发又黑又长
 * @Date 2022/8/23 16:18
 * @email zwb15083976291@163.com
 */
@Configuration
public class SecurityConfig {


    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    /**
     * token 验证
     *
     * @return
     */
    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() {
        return new JwtAuthenticationFilter();

    }

    /**
     * @param
     * @return
     * @throws Exception
     */
    /**
     * 匿名用户访问无权限资源时的异常处理
     *
     * @return
     */
    @Bean
    public JwtAuthenticationEntryPoint authenticationEntryPoint() {
        return new JwtAuthenticationEntryPoint();
    }

    /**
     * Jwt访问拒绝处理程序
     *
     * @return
     */
    @Bean
    public JwtAccessDeniedHandler accessDeniedHandler() {
        return new JwtAccessDeniedHandler();
    }


    /**
     * 决策管理器
     *
     * @return
     */
    @Bean
    public AccessDecisionManagerImpl accessDecisionManager() {
        return new AccessDecisionManagerImpl();
    }

    /**
     * 安全数据源
     *
     * @return
     */
    @Bean
    public SecureDataSourceImpl secureDataSource() {
        return new SecureDataSourceImpl();
    }

    /**
     * @return
     * @throws Exception
     */
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() throws Exception {
        String[] whiteList = {
                "/login", // 登录接口
                "/captcha", // 验证码接口
                "/favicon.ico",
                "/error",
                "/csrf", "/swagger-resources/**", "/webjars/**", "/v2/**", "/doc.html/**" // swagger
        };
        return new WebSecurityCustomizer() {
            @Override
            public void customize(WebSecurity web) {
                // 忽略的接口
                web.ignoring().mvcMatchers(whiteList);
            }
        };

    }


    /**
     * Spring security 配置
     *
     * @param http
     * @return
     * @throws Exception
     */
    @Autowired(required = false)
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {


        http
                .csrf().disable() // 关闭csrf
                // 关闭session 管理器
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .anyRequest().authenticated()
                // 动态权限配置
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        // 安全数据源
                        object.setSecurityMetadataSource(secureDataSource());
                        // 决策管理器
                        object.setAccessDecisionManager(accessDecisionManager());
                        return object;
                    }
                })
                .and()
                // 请求头控制
                .headers()
                .cacheControl();
        http.exceptionHandling()
                //未登录访问
                .authenticationEntryPoint(authenticationEntryPoint())
                //  权限不足访问
                .accessDeniedHandler(accessDeniedHandler());
        // 添加jtw 拦截器
        http.addFilterAt(this.jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        return http.build();

    }


}
